package com.gec.service.Impl;

import com.gec.dao.DeptDao;
import com.gec.dao.LeaveDao;
import com.gec.dao.ProcessConfigDao;
import com.gec.domain.Leave;
import com.gec.domain.PageBean;
import com.gec.domain.PageParam;
import com.gec.domain.ProcessConfig;
import com.gec.service.abst.LeaveService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class LeaveServiceImpl extends BaseService implements LeaveService {

    private final LeaveDao leaveDao;
    private final DeptDao deptDao;

    private final RuntimeService runtimeService;
    private final TaskService taskService;

    private final ProcessConfigDao procConfigDao;

    public LeaveServiceImpl(LeaveDao leaveDao, DeptDao deptDao, RuntimeService runtimeService, TaskService taskService, ProcessConfigDao procConfigDao) {
        this.leaveDao = leaveDao;
        this.deptDao = deptDao;
        this.runtimeService = runtimeService;
        this.taskService = taskService;
        this.procConfigDao = procConfigDao;
    }


    /*-----------------------[x][监听器用到的方法]------------------------------*/
    @Override
    public String getHigherDeptLeader(String deptId) {
        //{1}获取上一级部门的 Id
        String higherDept = deptDao.findHigherLevelDept(deptId);
        //{2}获取上一级部门的领导的 Id
        return deptDao.findDeptLeaderId(higherDept);
    }

    @Override
    public String getDeptLeader(String deptId) {
        return deptDao.findDeptLeaderId(deptId);
    }

    @Override
    public void updateAssigneeAndTask(String insID, String taskID, String assignee) {
        leaveDao.updateAssigneeAndTask(
                insID, taskID, assignee);
    }

    /*-----------------------[A][andy发起请假]------------------------------*/
	/*流程变量:
	   inputUser: 发起人 [这里bpmn文件中设置的占位符]
	                   [我要使用流程变量来入参]
	   startDate: 开始日期
	   endDate: 结束日期
	   reason: 请假原因
	   leaveType: 请假类型
	   days: 请假天数 [计算请假天数]
	   cancel: false   [这个是流程图流通条件]
	  */
    private Map<String, Object> setVariables(
            Leave leave) {
        HashMap<String, Object> data = new HashMap<>();
        //getInitiator == andy [userId]
        data.put("inputUser", leave.getInitiator());
        data.put("startDate", leave.getStartDate());
        data.put("endDate", leave.getEndDate());
        data.put("reason", leave.getReason());
        data.put("leaveType", leave.getLeaveType());
        data.put("days", leave.getDays());
        data.put("cancel", "false");
        return data;
    }

    public void startProcess(Leave leave) {
        //{1}查询出最新版本的请假流程的定义ID
        ProcessConfig config = procConfigDao.getProcessByCategory("请假流程");
        //{2}获取流程定义 ID [用作开启流程]
        String procDefID = config.getProcDefId();

        //{3.1}days: 请假天数 [计算请假天数]
        Date startDate = leave.getStartDate();
        Date endDate = leave.getEndDate();
        int days = calDays(startDate, endDate);
        //{3.2}设置天数到 Leave
        leave.setDays(days);
        leave.setProcDefId(procDefID);

        //{4}填充流程变量
        Map<String, Object> data = setVariables(leave);

        //格式: runtimeService.startProcessInstanceById(
        //		流程定义ID, 流程变量容器 );
        //{5}开启流程, 传入流程变量
        ProcessInstance ins = runtimeService.startProcessInstanceById(procDefID, data);
        //{6.1}填充流程实例 ID 到 Leave
        leave.setProcInstId(ins.getId());
        //{6.2}填充 '办理中' 到 Leave
        leave.setStatus("办理中");


        //{7}写入 Leave 对象到 t_leave 表中
        leaveDao.addLeave(leave);

        //{8}提交  andy 任务
        commitLeave(leave.getInitiator(), ins.getId());
    }

    private void commitLeave(
            String initiator, String insID) {
        //{1}传入两个参数 [如果, 我点了三次请假]
        Task task = taskService.createTaskQuery()
                .taskAssignee(initiator)
                .processInstanceId(insID)
                .singleResult();
        //{2}提交任务结束...
        taskService.complete(task.getId());
    }

    /*-----------------------[B][andy查看我发起的]------------------------------*/
    @Override
    public PageBean<Leave> queryMyInitiate(PageParam param, String initiator) {
        Page<Object> page = PageHelper.startPage(
                param.getPage(),
                param.getLimit(),
                true);
        //{3}查询我发起的请假。[t_leave表]
        List<Leave> list = leaveDao.queryMyInitiate(initiator);
        //{4}获取总记录数
        int count = (int) page.getTotal();
        PageBean<Leave> pBean = new PageBean<>();
        //{5}设置 [总记录数] 与 [列表]。
        pBean.setCount(count);
        pBean.setData(list);
        //{6}返回 pBean
        return pBean;
    }



    /*-----------------------[C][candy查看待审批的]------------------------------*/

    @Override
    public PageBean<Leave> queryWaitMyApprove(String assigneeId, PageParam param) {
        Page<Object> page = PageHelper.startPage(
                param.getPage(),
                param.getLimit(),
                true);
        List<Leave> list = leaveDao.queryWaitMyApprove(assigneeId);
        PageBean<Leave> pBean = new PageBean<>();
        pBean.setCount((int) page.getTotal());
        pBean.setData(list);
        return pBean;
    }


    /*-----------------------[D][Candy 审批 ANDY 请假]------------------------------*/
    //{1}先查再审批
    @Override
    public Leave queryMyTaskByTaskId(String taskId) {
        return leaveDao.queryMyTaskByTaskId(taskId);
    }


    //{2}审批代办的任务
    @Override
    public void updateStatusByInstance(String proInsID, String status) {
        int cnt = leaveDao.updateStatusByInstance(proInsID, status);
        if (cnt != 1) {
            throw new RuntimeException("更新状态失败");
        }
    }

    @Override
    public void clearTaskAndAssignee(String proInsID) {
        int cnt = leaveDao.clearTaskAndAssignee(proInsID);
        if (cnt != 1) {
            throw new RuntimeException("清空办理人失败");
        }
    }


    @Override
    public void completeMyApprove(Map<String, Object> map) {
        String deptId = (String) map.get("deptId");
        String appFlag = (String) map.get("appFlag");
        String taskId = (String) map.get("taskId");
        String higherLevelDept = deptDao.findHigherLevelDept(deptId);
        System.out.println("+--------------------------------------------------------------------------------+");
        System.out.println(deptId);
        System.out.println(appFlag);
        System.out.println(taskId);
        System.out.println(higherLevelDept);
        System.out.println("+--------------------------------------------------------------------------------+");
        //根据部门ID查询更高一级部门ID
        if ("top".equals(higherLevelDept)) {//如果父级是Top,表示当前是总经办
            map.put("bossApp", appFlag);
        } else {
            map.put("deptApp", appFlag);
        }

        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        String procInsId = task.getProcessInstanceId();
        String assignee = task.getAssignee();
        System.out.println("+-------------------------------+");
        System.out.println(task.getAssignee());
        System.out.println(procInsId);
        System.out.println("+-------------------------------+");
        //加入我已审批列表
        leaveDao.addRecordToHistoricLeave(procInsId, assignee);
        if (appFlag.equals("false")){
            leaveDao.updateStatusByInstance(procInsId, "已拒绝");
        }
        //把办理人置空【null】
        leaveDao.updateAssigneeAndTask(procInsId, null, null);
        //提交当前任务【candy,boss】
        taskService.complete(taskId, map);

    }

    @Override
    public void cancelProcess(String instId) {
        Task task = taskService.createTaskQuery()
                .processInstanceId(instId)
                .singleResult();
        HashMap<String, Object> data = new HashMap<>();
        data.put("cancel", "true");
        taskService.complete(task.getId(), data);
    }





    /*-----------------------[E][Candy 查看我已审批的 ]------------------------------*/

    @Override
    public PageBean<Leave> queryHistoryApproved(PageParam param, String assignee) {
        List<String> list = leaveDao.queryHistoryProcessInstanceIdByAssignee(assignee);
        if (list.size() == 0) {
            return new PageBean<>();
        }
        StringBuilder builder = new StringBuilder();
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            builder.append(iterator.next());
            if (iterator.hasNext()) builder.append(",");
        }
        Page<Object> page = PageHelper.startPage(
                param.getPage(), param.getLimit(), true);
        List<Leave> leaves = leaveDao.queryMyApproveByProcessInstanceIds(builder.toString());
        int count = (int) page.getTotal();
        PageBean<Leave> pBean = new PageBean<>();
        pBean.setCount(count);
        pBean.setData(leaves);
        pBean.setCode(0);
        return pBean;
    }


}
